#pragma once
#include "Socket.hpp"
#include <iostream>
#include <pthread.h>
#include <functional>

// using func_t = std::function<void(Socket*)>;
using func_t = std::function<std::string(std::string&, bool*)>;

class TcpServer;
class ThreadData
{
public:
    ThreadData(Socket* socket, TcpServer* tcp)
        :_socket(socket), _this(tcp)
    {}
public:
    Socket* _socket;
    TcpServer* _this;
};

class TcpServer
{
public:
    TcpServer(uint16_t port, func_t func)
        : _port(port), _listensocket(new TcpSocket()), _handler_request(func)
    {
        _listensocket->BuildListenSocket(_port, backlog);
    }

    static void* ThreadRoutine(void* args)
    {
        pthread_detach(pthread_self());

        ThreadData* td = static_cast<ThreadData*>(args);
        // td->_this->_handler_request(td->_socket);
        std::string instream;
        while(true)
        {
            bool error_code = true;
            //接收package
            // std::cout << "instream" << std::endl;
            if(!td->_socket->Recv(&instream, 1024)) continue;
            // std::cout << instream << std::endl;            //DEBUG
            //处理package
            // std::cout << "s_send" << std::endl;             //DEBUG
            std::string s_send = td->_this->_handler_request(instream, &error_code);
            // std::cout << s_send << std::endl;             //DEBUG
            if(error_code)
            {
                if(!s_send.empty())
                    td->_socket->Send(s_send);
            }
            else break;
            sleep(1);
        }

        //这里也没必要，因为_handler_request这个是个死循环
        td->_socket->CloseSockfd();
        delete td->_socket;
        delete td;
        return nullptr;
    }

    void loop()
    {
        while (true)
        {
            std::string peerip;
            uint16_t peerport;
            Socket *newsockfd = _listensocket->AcceptConnection(&peerip, &peerport);
            if(!newsockfd) continue; //防止空指针解引用
            std::cout << "新链接: sockfd: " << newsockfd->GetSockfd() << " client: " << peerip << ":" << peerport << std::endl;

            pthread_t tid;
            ThreadData* td = new ThreadData(newsockfd, this);
            pthread_create(&tid, nullptr, ThreadRoutine, td);
            // std::cout << "1" << std::endl; //DEBUG
            // sleep(10);
            // newsockfd->CloseSockfd();
        }
    }
    ~TcpServer()
    {
    }

private:
    uint16_t _port;
    Socket *_listensocket;
public:
    func_t _handler_request;
};